package com.sptpc.learnspring.security;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.sptpc.learnspring.global.exception.BusinessException;
import com.sptpc.learnspring.global.response.BusinessStatusCode;
import com.sptpc.learnspring.model.User;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Configuration
@Slf4j
public class JwtUtil {
    // 产线应用应该从配置文件中读取
    private static final String JWT_HEADER = "Authorization";
    private static final String JWT_PREFIX = "Bearer ";
    private static final String SECRET_KEY = "sptpc.com";
    private static final int EXPIRITION = 1000 * 60 * 60 * 24;

    /**
     * 创建JWT token
     */
    public static String createJWT(User user) {
        Date now = new Date();
        
        String token = Jwts.builder()
                .claim("username", user.getUsername())
                .claim("role", user.getRole())
                .setIssuedAt(now)
                .setExpiration(DateUtil.offsetMillisecond(now, EXPIRITION))
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();

        return token;
    }

    public static String createJWT(String username, String role) {
        Date now = new Date();

        String token = Jwts.builder()
                .claim("username", username)
                .claim("role", role)
                .setIssuedAt(now)
                .setExpiration(DateUtil.offsetMillisecond(now, EXPIRITION))
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();

        return token;
    }

    /**
     * 解析JWT token
     *
     * @param token JWT token
     * @return {@link Claims}
     */
    private static Claims parseJWT(String token) {
        try {
            Claims claims = Jwts.parser()
                    .setSigningKey(SECRET_KEY)
                    .parseClaimsJws(token)
                    .getBody();

            return claims;
        } catch (ExpiredJwtException e) {
            log.error("Token 已过期");
            throw new BusinessException(BusinessStatusCode.TOKEN_EXPIRED);
        } catch (UnsupportedJwtException e) {
            log.error("不支持的 Token");
            throw new BusinessException(BusinessStatusCode.TOKEN_PARSE_ERROR);
        } catch (MalformedJwtException e) {
            log.error("Token 无效");
            throw new BusinessException(BusinessStatusCode.TOKEN_PARSE_ERROR);
        } catch (SignatureException e) {
            log.error("无效的 Token 签名");
            throw new BusinessException(BusinessStatusCode.TOKEN_PARSE_ERROR);
        } catch (IllegalArgumentException e) {
            log.error("Token 参数不存在");
            throw new BusinessException(BusinessStatusCode.TOKEN_PARSE_ERROR);
        }
    }

    /**
     * 从 jwt token获取用户id
     * @param jwt JWT token
     * @return id
     */
    public static Long getIdFromToken(String jwt) {
        return Long.parseLong(
                parseJWT(jwt).get("id").toString());
    }

    /**
     * 从 jwt token获取用户名
     * @param jwt JWT token
     * @return 用户名
     */
    public static String getUsernameFromJWT(String jwt) {
        return parseJWT(jwt).get("username").toString();
    }

    /**
     * 从 jwt token获取用户角色
     * @param jwt JWT token
     * @return 用户角色
     */
    public static String getRoleFromJWT(String jwt) {
        return parseJWT(jwt).get("role").toString();
    }

    /**
     * 从 request 的 header 中获取 JWT token
     *
     * @param request 请求
     * @return JWT token
     */
    public static String getJwtFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader(JWT_HEADER);
        if (StrUtil.isNotBlank(bearerToken) && bearerToken.startsWith(JWT_PREFIX)) {
            return bearerToken.substring(JWT_PREFIX.length());
        }
        return null;
    }

}
